/**
 * 框架的配置项
 */
export interface AyakaOptions {
    /**
     * bot 的名字，用于区分不同的bot，默认为 ayaka-bot
     */
    botName?: string
    /**
     * 最低启动 cpu，高于该值时才会执行挂载，否则等待下个 tick再尝试挂载
     */
    minCpu?: number
    /**
     * 是否清除过期爬，房间，旗帜的 memory，默认不清理，传入数字可以指定清理的时间间隔
     */
    clearExpiredMemory?: number
    /**
     * 房间运行器
     * 将对每个有视野的房间运行一次该函数
     */
    roomRunner?: (room: Room) => unknown
    /**
     * creep 运行器
     * 将对所有的 creep 运行该函数
     */
    creepRunner?: (creep: Creep) => unknown
    /**
     * powerCreep 运行器
     * 将对所有 pc 运行该函数（包括未出生的 pc）
     */
    powerCreepRunner?: (creep: PowerCreep) => unknown
    /**
     * 全局运行器
     * 将在每个 tick 运行一次该函数
     */
    globalRunner?: () => unknown
}

/**
 * 生命周期回调函数
 */
export type LifeCycleCallback = () => unknown

/**
 * 生命周期名字
 * mounted - 挂载完成，此阶段用于挂载原型
 * tickStart - tick 开始
 * tickEnd - tick 结束
 */
export const LifeCycleNames = ['mounted', 'tickStart', 'tickEnd'] as const
export type LifeCycleName = (typeof LifeCycleNames)[number]

/**
 * 生命周期
 */
export type AppLifeCycle = {
    [key in LifeCycleName]: LifeCycleCallback[]
}

/**
 * 模块各生命周期
 */
export type LifeCycles = {
    [key in LifeCycleName]?: LifeCycleCallback
}

/**
 * 异常捕获方法
 * 调用 next 可以执行实际业务逻辑
 */
export type ErrorCatcher = <T extends (...args: unknown[]) => unknown>(next: T, ...args: unknown[]) => void

/**
 * 内存缓存方法
 * 调用 next 可以执行实际业务逻辑
 */
export type MemoryCacher = (next: () => unknown) => unknown

/**
 * 房间等级缓存
 */
export interface RoomLevel {
    [roomName: string]: number | undefined
}

/**
 * 房间等级变化回调函数
 * @param room 房间
 * @param level 等级
 * @param oldLevel 旧等级，如果没有就说明是新房间或者是初次挂载
 */
export type RoomLevelChangeCallback = (room: MyRoom, level: number, oldLevel?: number) => void

/**
 * 定时函数
 */
export type TimerCallback = () => void

/**
 * 框架记忆
 */
export interface AyakaMemory {
    /**
     * bot 的名字，用于区分不同的 bot，默认为 ayaka-bot
     */
    botName: string
    /**
     * 挂载框架的时间，这也是全局重置的时间
     */
    mountedTime: number
    /**
     * 平均cpu
     */
    aveCpu?: number
    /**
     * 是否启动 memory 缓存（仙术），默认不启用
     */
    enableMemoryCache?: boolean
}

declare global {
    interface Memory {
        ayaka: AyakaMemory
        /**
         * boolean 类型的属性可以放这里，起开关某些功能的作用
         */
        switchs: Record<string, boolean>
    }

    // TODO: 自己房间和别人房间还是不一样，应该用两个类型
    interface MyRoom extends Room {
        controller: StructureController
    }
}

/**
 * 任意函数类型
 */
export type AnyFunction = (...args: any[]) => any

/**
 * 任意对象类型
 */
export type AnyObject = Record<string, any>

/**
 * 任意构造函数类型
 */
export type AnyConstructor = new (...args: any[]) => any

/**
 * 任意类类型
 */
export type AnyClass = AnyConstructor & AnyObject

/**
 * 取出对象类型中所有的值
 */
export type ValueOf<T> = T[keyof T]

/**
 * 运行时传入的回调函数，原类型返回值没有undefined，这里加上
 */
export type RoomCallBack = (roomName: string) => CostMatrix | boolean | undefined
